package com.ffsky.cordova.fragment;

import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


import com.ffsky.cordova.CordovaKit;
import com.ffsky.cordova.R;

import org.apache.cordova.ConfigXmlParser;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaInterfaceImpl;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaPreferences;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewImpl;
import org.apache.cordova.PluginEntry;
import org.apache.cordova.engine.SystemWebView;
import org.apache.cordova.engine.SystemWebViewEngine;

import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import androidx.fragment.app.Fragment;

/**
 * 来源 https://github.com/Adobe-Marketing-Cloud-Apps/app-sample-android-phonegap/blob/master/platforms/android/src/info/geometrixx/webviewapp/HomeFragment.java
 *
 */
public class AdobeCordovaFragment extends Fragment implements CordovaInterface {


    // Plugin to call when activity result is received
    protected CordovaPlugin activityResultCallback = null;
    protected boolean activityResultKeepRunning;

    // Keep app running when pause is received. (default = true)
    // If true, then the JavaScript and native code continue to run in the background
    // when another application (activity) is started.
    protected boolean keepRunning = true;

    //Instance of the actual Cordova WebView
    CordovaWebView aemView;
    protected CordovaPreferences preferences;
    protected ArrayList<PluginEntry> pluginEntries;
    protected CordovaInterfaceImpl cordovaInterface;

    private final ExecutorService threadPool = Executors.newCachedThreadPool();

    public static AdobeCordovaFragment newInstance() {
        AdobeCordovaFragment fragment = new AdobeCordovaFragment();
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        LayoutInflater localInflater = inflater.cloneInContext(new CordovaContext(getActivity(), this));
        View rootView = localInflater.inflate(R.layout.lib_cordova_ext_adobe_fragment, container, false);
        SystemWebView mWebView = (SystemWebView) rootView.findViewById(R.id.myWebView);

        CordovaKit.getInstance().load(getContext());

        cordovaInterface =  new CordovaInterfaceImpl(getActivity(),CordovaKit.getInstance().getThreadPool());
        preferences = CordovaKit.getInstance().getPreferences();
        preferences.setPreferencesBundle(getActivity().getIntent().getExtras());
        pluginEntries =CordovaKit.getInstance().getPluginEntries();


        aemView = new CordovaWebViewImpl(new SystemWebViewEngine(mWebView));
        cordovaInterface.onCordovaInit(aemView.getPluginManager());

        if (!aemView.isInitialized()) {
            aemView.init(cordovaInterface, pluginEntries, preferences);
        }
        aemView.loadUrlIntoView(CordovaKit.getInstance().getLaunchUrl(), true);

//        mWebView.loadUrl(Config.getStartUrl());
        return rootView;
    }

    @Override
    public void onPause() {
        super.onPause();
        if (this.aemView != null) {
            // CB-9382 If there is an activity that started for result and main activity is waiting for callback
            // result, we shoudn't stop WebView Javascript timers, as activity for result might be using them
//            boolean keepRunning = this.keepRunning || this.cordovaInterface.activityResultCallback != null;
            boolean keepRunning = this.keepRunning;
            this.aemView.handlePause(keepRunning);
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (this.aemView == null) {
            return;
        }
        this.aemView.handleStop();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (this.aemView == null) {
            return;
        }
//        if (! this.getWindow().getDecorView().hasFocus()) {
//            // Force window to have focus, so application always
//            // receive user input. Workaround for some devices (Samsung Galaxy Note 3 at least)
//            this.getWindow().getDecorView().requestFocus();
//        }
        this.aemView.handleResume(this.keepRunning);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (this.aemView != null) {
            aemView.handleDestroy();
        }
    }

    @Override
    public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {

    }

    @Override
    public void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) {

    }

    @Override
    public boolean hasPermission(String permission) {
        return false;
    }

    @Override
    public void setActivityResultCallback(CordovaPlugin plugin) {
        this.activityResultCallback = plugin;
    }

    /**
     * Launch an activity for which you would like a result when it finished. When this activity exits,
     * your onActivityResult() method is called.
     *
     * @param command           The command object
     * @param intent            The intent to start
     * @param requestCode       The request code that is passed to callback to identify the activity
     */
    public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
        this.activityResultCallback = command;
        this.activityResultKeepRunning = this.keepRunning;

        // If multitasking turned on, then disable it for activities that return results
        if (command != null) {
            this.keepRunning = false;
        }

        // Start activity
        super.startActivityForResult(intent, requestCode);

    }

    //
    // Cordova
    //

    /**
     * Called when a message is sent to plugin.
     *
     * @param id
     *            The message id
     * @param data
     *            The message data
     * @return Object or null
     */
    public Object onMessage(String id, Object data) {
        return null;
    }

    // Cordova Interface Events
    @Override
    public ExecutorService getThreadPool() {
        return threadPool;
    }

    @Override
    /**
     * Called when an activity you launched exits, giving you the requestCode you started it with,
     * the resultCode it returned, and any additional data from it.
     *
     * @param requestCode       The request code originally supplied to startActivityForResult(),
     *                          allowing you to identify who this result came from.
     * @param resultCode        The integer result code returned by the child activity through its setResult().
     * @param data              An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
     */
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        CordovaPlugin callback = this.activityResultCallback;
        if (callback != null) {
            callback.onActivityResult(requestCode, resultCode, intent);
        }
    }


    /**
     * A {@link ContextWrapper} that also implements {@link CordovaInterface} and acts as a proxy between the base
     * activity context and the fragment that contains a {@link CordovaWebView}.
     */
    private class CordovaContext extends ContextWrapper implements CordovaInterface {
        CordovaInterface cordova;

        public CordovaContext(Context base, CordovaInterface cordova) {
            super(base);
            this.cordova = cordova;
        }

        public void startActivityForResult(CordovaPlugin command,
                                           Intent intent, int requestCode) {
            cordova.startActivityForResult(command, intent, requestCode);
        }

        public void setActivityResultCallback(CordovaPlugin plugin) {
            cordova.setActivityResultCallback(plugin);
        }

        public Activity getActivity() {
            return cordova.getActivity();
        }

        @Override
        public Context getContext() {
            return cordova.getActivity();
        }

        public Object onMessage(String id, Object data) {
            return cordova.onMessage(id, data);
        }

        public ExecutorService getThreadPool() {
            return cordova.getThreadPool();
        }

        @Override
        public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {

        }

        @Override
        public void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) {

        }

        @Override
        public boolean hasPermission(String permission) {
            return false;
        }

    }
}
